<!--
 * @Author: JiraiyaChen 49619401+JiraiyaChen@users.noreply.github.com
 * @Date: 2024-01-04 16:11:05
 * @LastEditors: JiraiyaChen 979526234@qq.com
 * @LastEditTime: 2025-06-19 15:57:59
 * @Description: el-table 封装v2版本 简化代码
 * @FilePath: \cl-project-demo\src\components\cl-table-v2\index.vue
 * 
 * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. 
-->
<template>
  <div class="table-box">
    <div class="option-box mb-3 w-full flex items-center justify-between">
      <div class="flex items-center gap-3" :class="filterFormItem.length !== 0 ? 'w-70%' : ''">
        <ClForm
          v-if="filterFormItem.length !== 0"
          ref="refForm"
          label-width="110px"
          :form-item="filterFormItem"
          :inline="true"
          @update:formItem="onUpdateFormItem"
        >
          <template #opt-btn>
            <el-button v-if="showSearch" type="primary" plain :loading="loadingTable" @click="onSearch">查询</el-button>
          </template>
        </ClForm>
        <slot name="cl-span" />
      </div>
      <div class="option-btn w-30% flex justify-end" :class="filterFormItem.length !== 0 ? 'w-30%' : 'w-full'">
        <slot
          name="opt-btn"
          :multiple-selection="multipleSelection"
          :multiple-selection-id="multipleSelectionId"
          :filter-data="refForm?.formData"
        />
      </div>
    </div>
    <div class="row2 mb-3 inner-table-box">
      <el-table
        id="cl-table"
        ref="refTable"
        v-loading="loadingTable"
        class="cl-table"
        table-layout="auto"
        tooltip-effect="light"
        :data="realTableData"
        style="width: 100%"
        :max-height="maxHeight"
        :highlight-current-row="highlight"
        :span-method="spanMethod"
        :border="showBorder"
        :stripe="stripe"
        header-cell-class-name="my-header-cell-row"
        cell-class-name="my-cell-row"
        @current-change="handleHeightLight"
        @selection-change="handleSelectionChange"
        @header-click="onHeaderClick"
        @row-click="handleRowClick"
      >
        <el-table-column v-if="showSelection" type="selection" :width="55" :selectable="selectable" fixed="left" />
        <el-table-column v-if="showIndex" label="序号" type="index" :width="65" fixed="left" />
        <el-table-column
          v-for="item in columnList"
          :key="item"
          :fixed="item.fixed"
          :prop="item.prop"
          :label="item.label"
          :width="item.width"
          :show-overflow-tooltip="item.isTooltip ?? true"
        >
          <template v-if="item.component" #default="{ row }">
            <component
              :is="item.component"
              :row-data="row"
              :data-key="item.prop"
              :field-value="row[item.prop]"
              :column="item"
            />
          </template>
        </el-table-column>
        <slot name="column" />
      </el-table>
    </div>
    <div v-if="pageTotal !== 0" class="row3 flex justify-end">
      <el-pagination
        v-if="showPage"
        v-model:current-page="elPage.pageNo"
        v-model:page-size="elPage.pageSize"
        :page-sizes="[10, 20, 30, 50, 100]"
        layout="total, sizes, prev, pager, next"
        :total="pageTotal"
        :small="true"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { type PropType } from 'vue';

interface ColumnProps {
  prop: string
  label: string
  width?: string | number
  fixed?: string
  isTooltip?: string
  component?: any
  compKey?: string
}
interface FilterFormItem {
  key: string // formData 的字段名
  value: any
  name: string // label 名字
  formType: string // form 表单的种类
  elementConfig: any //
}
const props = defineProps({
  // 表格数据来源
  tableData: {
    type: [Array, Function],
    required: true
  },
  // 表格 筛选
  filterFormItem: {
    type: Array as PropType<FilterFormItem[]>,
    default: () => []
  },
  // 列
  columnList: {
    type: Array as PropType<ColumnProps[]>,
    default: () => []
  },
  showPage: {
    type: Boolean,
    default: true
  },
  showSearch: {
    type: Boolean,
    default: true
  },
  maxHeight: {
    type: Number,
  },
  highlight: {
    type: Boolean,
    default: false
  },
  stripe: {
    type: Boolean,
    default: false
  },
  showBorder: {
    type: Boolean,
    default: false
  },
  spanMethod: {
    type: Function
  },
  // 高光列表
  highlightInfo: {
    type: Object,
  },
  showSelection: {
    type: Boolean,
    default: false
  },
  showIndex: {
    type: Boolean,
    default: false
  },

  selectable: {
    type: Function,
    default: () => {
      return true
    }
  }
})
onMounted(() => {
  initTable()
})
// 分页
const pageTotal = ref(0)
const elPage = ref({ pageNo: 1, pageSize: 10 })
const handleSizeChange = val => {
  elPage.value.pageSize = val
  initTable()
}
const handleCurrentChange = val => {
  elPage.value.pageNo = val
  initTable()
}
// 筛选框
const refForm = ref<any>(null)
const emit = defineEmits(['update:formItem', 'update:highlightInfo', 'handleSelectionChange', 'header-click', 'sentTableData', 'row-click'])
const onUpdateFormItem = (val, item) => {
  const temp = cloneDeep(props.filterFormItem)
  emit('update:formItem', temp)
  initTable()
}
const onHeaderClick = (column) => {
  emit('header-click', column)
}
const handleRowClick = (row) => {
  emit('row-click', row)
}
const onSearch = () => {
  initTable()
}


const refTable = ref<any>(null)
const setCurrent = () => {
  if (props.highlightInfo) {
    const id = props.highlightInfo.id
    const targetIndex = realTableData.value.findIndex((m) => m.id === id)
    if (targetIndex !== -1) {
      refTable.value!.setCurrentRow(realTableData.value[targetIndex])
    }
  }

}
const handleHeightLight = (val) => {
  emit('update:highlightInfo', val)
}
const multipleSelection = ref([])
const multipleSelectionId = ref([])
const handleSelectionChange = (val) => {
  multipleSelection.value = val
  multipleSelectionId.value = val.map((m) => m.id)
  emit('handleSelectionChange', val)
}
// 表格数据
const loadingTable = ref(false)
const realTableData = ref<any>([])
const initTable = async () => {
  try {
    if (typeof props.tableData === 'function') {
      const filterData = refForm.value?.formData
      loadingTable.value = true
      let tableRequest = {}
      if (props.showPage) {
        tableRequest = { ...elPage.value, ...filterData }
      } else {
        tableRequest = filterData
      }
      const data = await props.tableData(tableRequest)
      const { records, rows, total } = data
      realTableData.value = rows ?? records ?? data

      pageTotal.value = total ?? 0
      loadingTable.value = false
      emit('sentTableData', realTableData.value)
    } else {
      realTableData.value = props.tableData
      pageTotal.value = props.tableData.length
    }
    // 默认高亮
    // setCurrent()
  } catch (error) {
    console.log('🐷 🐽 initTable 🐽 error👉👉👉', error)
    loadingTable.value = false
  }
}
defineExpose({
  initTable,
  refForm,

})
</script>
<style scoped>
@import url('./index.scss');
</style>
<style scoped lang="scss">
:deep(.el-form-item__label) {
  display: none;
}
:deep(.el-form-item) {
  margin-bottom: 0 !important;
}
:deep(.btn-prev) {
  background-color: transparent !important;
}

:deep(.btn-next) {
  background-color: transparent !important;
}

:deep(.el-pager) {
  .number {
    color: #3f3f44;
    background-color: transparent !important;
  }
}
</style>
